package com.cg.bank.web.action;

import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.cg.bank.domain.Transaction;
import com.cg.bank.domain.User;
import com.cg.bank.service.ManagerImpl;
import com.cg.bank.service.ManagerInterface;
import com.cg.bank.util.Page;
import com.cg.bank.web.util.AppException;

/**
 * 交易Action
 * 
 * @author chunges
 * @date 2018年8月31日 上午7:09:24
 * @version V1.0
 */

public class TransactionAction extends BaseAction {
	private static final String DEPOSIT = "存款";
	private static final String WITHDRAWAL = "取款";
	private static final String TRANSFER = "转账";
	private static final String GATHERING = "收款";
	//private static final String FASTPAY = "快捷支付";
	
	/**
	 * 余额查询Action
	 * 
	 * @param mapping mapping信息
	 * @param form 存款表单Bean
	 * @param request request请求
	 * @param response response对象
	 * @throws Exception
	 */
	public ActionForward queryBalance(ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(USERSESSIONFLAG);
		if (session.getAttribute("update") != null) {
			ManagerInterface manager = ManagerImpl.getInstance();
			double balance = manager.queryBalance(user);
			// 更新session中的用户余额
			user.setBalance(balance);
			session.setAttribute(USERSESSIONFLAG, user);
		}
		response.setContentType("text/text;charset=utf-8");
		PrintWriter printWriter = response.getWriter();
		printWriter.write(String.valueOf(user.getBalance()));
		return null;
	}
	
	/**
	 * 存款Action
	 * 
	 * @param mapping mapping信息
	 * @param form 存款表单Bean
	 * @param request request请求
	 * @param response response对象
	 * @throws Exception
	 */
	public ActionForward deposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, 
			HttpServletResponse response) throws Exception {
		String tempMoney = request.getParameter("money");
        if (tempMoney == null || "".equals(tempMoney)) {
            request.setAttribute("money", "请输入存款金额:(");
        } else { 
        	try {
                double money = Double.parseDouble(tempMoney);
                ManagerInterface manager = ManagerImpl.getInstance();
                User user = (User) request.getSession().getAttribute("user");
                manager.deposit(user, money);
                Transaction transaction = createTransactionRecord(user, null, money, DEPOSIT);
                // 添加存款成功交易记录
                manager.addTransactionRecord(transaction);
                // 处理结果
                processResult(request, money, DEPOSIT);
            } catch (NumberFormatException e) {
            	// 非法输入金额(如30A)
            	throw new AppException("transaction.error.depositInput");
            }
        }
        return mapping.findForward("deposit");
	}
	
	/**
	 * 取款Action
	 * 
	 * @param mapping mapping信息
	 * @param form 取款表单Bean
	 * @param request request请求
	 * @param response response对象
	 * @throws Exception
	 */
	public ActionForward withdrawal(ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String tempMoney = request.getParameter("money");
        if (tempMoney == null || "".equals(tempMoney)) {
            request.setAttribute("money", "请输入取款金额:(");
        } else {
            try {
                double money = Double.parseDouble(tempMoney);
                ManagerInterface manager = ManagerImpl.getInstance();
                User user = (User) request.getSession().getAttribute(USERSESSIONFLAG);
                manager.withdrawal(user, money);
                // 添加取款成功交易记录
                Transaction transaction = createTransactionRecord(user, null, money, WITHDRAWAL);
                manager.addTransactionRecord(transaction);
                // 处理结果
                processResult(request, money, WITHDRAWAL);
            } catch (NumberFormatException e) {
            	// 非法取款输入金额(如100A)
            	throw new AppException("transaction.error.withdrawalInput");
            }
        }
        return mapping.findForward("withdrawal");
	}
	
	/**
	 * 转账Action
	 * 
	 * @param mapping mapping信息
	 * @param form 转账表单Bean
	 * @param request request请求
	 * @param response response对象
	 * @throws Exception
	 */
	public ActionForward transfer(ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Map<String, Object> transactionMap = checkForm(request);
		String toAccount = (String) transactionMap.get("toAccount");
		request.setAttribute("toAccount", toAccount);
        // 校检通过得到transferMoney属性
        if (transactionMap.get("transferMoney") != null) {
            ManagerInterface manager = ManagerImpl.getInstance();
            User fromUser = (User) request.getSession().getAttribute(USERSESSIONFLAG);
            double money = (double) transactionMap.get("transferMoney");
            // 查询收款人信息
            User toUser = manager.queryUserByAccount(toAccount);
            manager.transfer(fromUser, toUser, money);
            
            // 添加转账记录到发起人
            Transaction transaction = createTransactionRecord(fromUser, toAccount, money, TRANSFER);
            // 添加转账记录到收款人
            Transaction transaction2 = createTransactionRecord(toUser, fromUser.getAccount(), money, GATHERING);
            manager.addTransactionRecord(transaction);
            manager.addTransactionRecord(transaction2);
            // 处理结果
            processResult(request, money, TRANSFER);
        } else {
            // 数据校检出错将map存储到request
            request.setAttribute("errorsMap", transactionMap);
        }
        return mapping.findForward("transfer");
	}
	
	/**
	 * 查询个人交易记录Action
	 * 
	 * @param mapping mapping信息
	 * @param form 
	 * @param request request请求
	 * @param response response对象
	 * @throws Exception
	 */
	public ActionForward queryRecords(ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		try {
			// 获取需要查询的分页号 param中获取的是pageno数值
			getAndSaveRecord(Integer.parseInt(request.getParameter("param")), request, response);
		} catch(RuntimeException e) {
			// 可能出现空指针或则转换异常
			throw new AppException("transaction.error.queryRecordInput");
		}
        
        return mapping.findForward("record");
	}
	
	/**
	 * 查询并保存交易记录
	 * 
	 * @param pageno 需要查询的分页
	 * @param session 用户session
	 * @throws Exception
	 */
	private void getAndSaveRecord(int pageno, HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(USERSESSIONFLAG);
		// 设定查询的总记录并创建分页器
		Page page = processCreatePage(session);
		page.setPageno(pageno);
		Map<Integer, List<Transaction>> recordMap = processCreateRecodeMap(session);
		if (recordMap.get(pageno) == null) {
			List<Transaction> record;
			ManagerInterface manager = ManagerImpl.getInstance();
			if (ROOTACCOUNT.equals(user.getAccount())) {
				record = manager.queryAllTransactionRecord(page);
			} else {
				record = manager.queryTransactionRecordByAccount(user, page);
			}
			if (record != null) {
				// 缓存分页记录并保存记录Map/page到session
				recordMap.put(pageno, record); 
				session.setAttribute("recordMap", recordMap);
				session.setAttribute("page", page);
				// 设定当前分页记录
				request.setAttribute("recordMap", record);
			}
    	} else {
    		// 从缓存中获得分页记录
    		request.setAttribute("recordMap", recordMap.get(pageno));
    		System.out.println("缓存查询...");
		}
	}
	
	/**
	 * 处理创建记录结果Map
	 * 
	 * @param session
	 * @return recordMap
	 */
	@SuppressWarnings("unchecked")
	private Map<Integer, List<Transaction>> processCreateRecodeMap(HttpSession session) {
		Map<Integer, List<Transaction>> recordMap  = (Map<Integer, List<Transaction>>) session.getAttribute("recordMap");
		return recordMap == null ? new HashMap<>():recordMap;
	}
	
	/**
	 * 处理创建分页器
	 * 
	 * @param session
	 * @return page
	 */
	private Page processCreatePage(HttpSession session) {
		Page page = (Page) session.getAttribute("page");
		return page == null ? new Page() : page;
	}

	/**
     * 创建交易记录
     *
     * @param currentUser 当前用户
     * @param account 收款/转账 账户
     * @param money 交易金额
     * @return transaction 交易信息bean
     */
    private Transaction createTransactionRecord(User currentUser, String account, 
    		double money, String transactionModel) {
    	Date date = new Date();
    	// 获取日期格式对象。自定义风格时间
    	DateFormat dateFormat = new SimpleDateFormat("yyyy年M月d日 HH:MM");
    	String dateStr = dateFormat.format(date);
    	Transaction transaction = new Transaction();
        transaction.setUser(currentUser);
        transaction.setType(transactionModel);
        transaction.setMoney(money);
        // 根据交易类型更新交易记录中余额
        if(transactionModel.equals(DEPOSIT) || transactionModel.equals(GATHERING)) {
        	transaction.setBalance(currentUser.getBalance() + money);
        } else {
            transaction.setBalance(currentUser.getBalance() - money);
		}
        StringBuilder detail = new StringBuilder(100);
        detail.append("您尾号").append(currentUser.getAccount().substring(7)).append("卡");
        // 截取账户最后4位
        //detail.append(currentUser.getAccount().substring(7));
        // detail.append("卡");
        detail.append(dateStr).append(" ");
        // 交易时间与交易类型之间插入空格
        // detail.append(" ");
        // 转账额外处理
        if(transactionModel.equals(TRANSFER)){
            detail.append("转账给").append(account).append(" ");
        	//detail.append(account);
        	//detail.append(" ");
        } else if (transactionModel.equals(GATHERING)) {
        	detail.append("收到来自").append(account).append("的转账金额");
        	//detail.append(account);
        	//detail.append("的转账金额");
         } else {
        	detail.append(transactionModel);
         }
         detail.append(money).append("元，余额").append(transaction.getBalance()).append("元。【CG银行】");
        // detail.append("元，余额");
        // detail.append(transaction.getBalance());
       //  detail.append("元。【CG银行】");
         transaction.setDetail(detail.toString());
         return transaction;
    }
    
    /**
     * 处理交易结果
     *
     * @param request
     * @param money
     */
    private void processResult(HttpServletRequest request, double money, String transactionType) {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        // 根据交易类型更新session中余额
        if(transactionType.equals(DEPOSIT) || transactionType.equals(GATHERING)) {
        	user.setBalance(user.getBalance() + money);
        } else {
        	user.setBalance(user.getBalance() - money);
		}
        session.setAttribute("user", user);
        request.setAttribute("result", "操作成功:)");
    }
    
    /**
     * 校检转账表单数据
     *
     * @param request request请求
     * @return 校检<strong>通过时</strong>能获取transferMoney属性
     * <p>{"toAccount", String toAccount}</p>
     * <p>{"transferMoney",double money}</p>
     */
    private Map<String, Object> checkForm (HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        String toAccount = request.getParameter("toAccount");
        String tempMoney = request.getParameter("money");
        if (toAccount == null || toAccount.length()!=11) {
            map.put("toAccount", "请输入正确收账的账户:(");
        }
        if (tempMoney == null || "".equals(tempMoney)) {
            map.put("money", "请输入转账金额:(");
        } else {
            try {
                // 校检数据成功时放入map
                map.put("transferMoney", Double.parseDouble(tempMoney));
                map.put("toAccount", toAccount);
            } catch (NumberFormatException e) {
               // map.put("money", "非法转账金额输入:(");
            	throw new AppException("transaction.error.transferInput");
            }
        }
        return map;
    }

}